#ifndef _NE_LOG_H_
#define _NE_LOG_H_

#include <system/Mutex.h>
#include <system/Timer.h>

namespace ne
{
    /* TODO: Format for output
        Code              Format
        %c                character
        %d                signed integers
        %i                signed integers
        %e                scientific notation, with a lowercase "e"
        %E                scientific notation, with a uppercase "E"
        %f                floating point
        %g                use %e or %f, whichever is shorter
        %G                use %E or %f, whichever is shorter
        %o                octal
        %s                a string of characters
        %u                unsigned integer
        %x                unsigned hexadecimal, with lowercase letters
        %X                unsigned hexadecimal, with uppercase letters
        %p                a pointer
        %n                the argument shall be a pointer to an integer into which is placed the number of characters written so far
        %%                a percent '%' sign
        %-                right-justified
    */

    /* TODO: Format for input
        Code              Format
        %c                a single character
        %d                a decimal integer
        %i                an integer
        %e %f %g          a floating-point number
        %o                an octal number
        %s                a string
        %u                an unsigned integer
        %x                a hexadecimal number
        %p                a pointer
        %n                an integer equal to the number of characters read so far
        %[]               a set of characters
        %%                a percent '%' sign
    */

    /* TODO: Constant Escape Sequences
        Escape Sequence   Description
        \'                Single quote
        \"                Double quote
        \\                Backslash
        \nnn              Octal number (nnn)
        \0                Null character (really just the octal number zero)
        \a                Audible bell
        \b                Backspace
        \f                Formfeed
        \n                Newline
        \r                Carriage return
        \t                Horizontal tab
        \v                Vertical tab
        \xnnn             Hexadecimal number (nnn)
    */

    enum LogLevel
    {
        LL_DEBUG = 0,
        LL_LOG,
        LL_WARNING,
        LL_ERROR
    };

    class NEAPI Log
    {
        public:
            explicit Log(const std::string &fileName,
                         const LogLevel level=LL_LOG);

            ~Log();

            const std::string& getFileName() const;

            void setLevel(const LogLevel level);

            LogLevel getLevel() const;

            void setTimeFormat(const std::string &format);

            const std::string& getTimeFormat() const;

            bool open();

            bool close();

            bool out(const std::string &format, va_list args);

            bool out(const LogLevel level, const std::string &format, va_list args);

            bool out(const std::string &format, ...);

            bool out(const LogLevel level, const std::string &format, ...);

            Log& operator << (const std::string &str);

        private:
            Log();

            Log(const Log &);

            Log& operator = (const Log &);

        public:
            static bool Out(const std::string &format, ...);

            static bool Out(const LogLevel level, const std::string &format, ...);

        public:
            static const char * const LOG_LEVEL_MESSAGES[];
            static Log DefaultLog;

        private:
            Mutex mMutex;
            std::string mFileName;
            LogLevel mLevel;
            std::string mTimeFormat;
    };
}

#endif
